﻿using BZ.Core;
using NDK.Motion.Card;
using EC_6000_Motion_Assistant.SDK;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Threading;

namespace NDK.Motion.MachineResources
{
    public enum AXIS_TYPE
    {
        X, Y, Z, R
    }

    [Serializable]
    public class Axis : INotifyPropertyChanged
    {
        private IMotionCard _card;   //所属卡
        private int _axisID;         //轴的唯一标识
        private string _Name;    //轴名称
        private double _ratio;       //脉冲与实际位置换算比例
        private double _lead = 10;        //轴的导程
        private double _gratingScale;//轴光栅尺分辨率
        private int _pulse = 10000;           //一圈对应的脉冲数

        private double _errorBand = 0.01;      //诊断到位与否的误差(单位mm)
        //回零参数
        private bool _isEnableHome = true;
        private double _homeStartVel = 10;
        private double _homeVel = 5;
        private double _homeAcc = 50;
        private double _homeOffset = 0;
        private DIR_ENUM _homeDir;
        private PRA_HOME_ENUM _homeMode;
        private PRA_SF_ENUM _homeCure;
        private int _homeOrder;//回零优先级
        private double _stopDec = 40000;
        //工作参数
        private double _workVel;
        private double _workAcc;
        private double _workDec;
        //jog参数
        private double _jogAcc;
        private double _jogDec;
        private double _jogSF;
        //用户交互参数
        [NonSerialized]
        private bool _isStop;        //是否需要停止
        private bool _isEnableUserLimit;
        private double _userLimitP;
        private double _userLimitN;
        private double _maxVel;
        private int _servoOnOrder;
        private int _servoOffOrder;

        private AXIS_TYPE _type = AXIS_TYPE.X;

        // Events
        public event PropertyChangedEventHandler PropertyChanged;

        #region 属性

        public IMotionCard Card
        {
            get
            {
                return _card;
            }

            set
            {
                _card = value;
            }
        }
        public int CardID
        {
            get
            {
                return _card.CardID;
            }
            set
            {
                //_card.CardID = value;
            }
        }
        public int AxisID
        {
            get
            {
                return _axisID;
            }

            set
            {
                _axisID = value;
            }
        }

        public string Name
        {
            get
            {
                return _Name;
            }

            set
            {
                _Name = value;
            }
        }

        public double Ratio
        {
            get
            {
                _ratio = (int.Parse((_pulse / _gratingScale).ToString()) / Convert.ToInt16(_lead));

                return _ratio;
            }
        }

        public double ErrBand
        {
            get
            {
                return _errorBand;
            }

            set
            {
                _errorBand = value;
            }
        }

        public double HomeVel
        {
            get
            {
                return _homeVel;
            }

            set
            {
                _homeVel = value;
            }
        }

        public double HomeAcc
        {
            get
            {
                return _homeAcc;
            }

            set
            {
                _homeAcc = value;
            }
        }

        public double HomeOffset
        {
            get
            {
                return _homeOffset;
            }

            set
            {
                _homeOffset = value;
            }
        }

        public DIR_ENUM HomeDir
        {
            get
            {
                return _homeDir;
            }

            set
            {
                _homeDir = value;
            }
        }

        public PRA_HOME_ENUM HomeMode
        {
            get
            {
                return _homeMode;
            }

            set
            {
                _homeMode = value;
            }
        }

        public double MoveVel
        {
            get
            {
                return _workVel;
            }

            set
            {
                _workVel = value;
            }
        }

        public double MaxVel
        {
            get
            {
                return _maxVel;
            }

            set
            {
                _maxVel = value;
            }
        }
        public double MoveAcc
        {
            get
            {
                return _workAcc;
            }

            set
            {
                _workAcc = value;
            }
        }

        public double MoveDec
        {
            get
            {
                return _workDec;
            }

            set
            {
                _workDec = value;
            }
        }


        public double JogAcc
        {
            get
            {
                return _jogAcc;
            }

            set
            {
                _jogAcc = value;
            }
        }

        public double JogDec
        {
            get
            {
                return _jogDec;
            }

            set
            {
                _jogDec = value;
            }
        }

        public bool IsStop
        {
            get
            {
                return _isStop;
            }

            set
            {
                _isStop = value;
            }
        }

        public double SPel
        {
            get
            {
                return _userLimitP;
            }

            set
            {
                _userLimitP = value;
            }
        }

        public double SMel
        {
            get
            {
                return _userLimitN;
            }

            set
            {
                _userLimitN = value;
            }
        }

        public bool IsEnableSoftLimit
        {
            get
            {
                return _isEnableUserLimit;
            }

            set
            {
                _isEnableUserLimit = value;
            }
        }

        public PRA_SF_ENUM HomeCurve
        {
            get
            {
                return _homeCure;
            }

            set
            {
                _homeCure = value;
            }
        }

        public bool IsEnableHome
        {
            get
            {
                return _isEnableHome;
            }

            set
            {
                _isEnableHome = value;
            }
        }
        public double HomeStartVel
        {
            get
            {
                return _homeStartVel;
            }

            set
            {
                _homeStartVel = value;
            }
        }

        public double JogSF
        {
            get
            {
                return _jogSF;
            }

            set
            {
                _jogSF = value;
            }
        }

        public double Lead
        {
            get
            {
                return _lead;
            }

            set
            {
                _lead = value;
            }
        }

        public double GratingScale
        {
            get
            {
                return _gratingScale;
            }

            set
            {
                _gratingScale = value;
            }
        }

        public int HomeOrder
        {
            get
            {
                return _homeOrder;
            }

            set
            {
                _homeOrder = value;
            }
        }

        public double StopDec
        {
            get
            {
                return _stopDec;
            }

            set
            {
                _stopDec = value;
            }
        }

        public int Pulse
        {
            get { return _pulse; }
            set { _pulse = value; }
        }
        public int ServoOnOrder
        {
            get { return _servoOnOrder; }
            set { _servoOnOrder = value; }
        }
        public int ServoOffOrder
        {
            get { return _servoOffOrder; }
            set { _servoOffOrder = value; }
        }

        public AXIS_TYPE Type
        {
            get { return _type; }
            set { _type = value; }
        }


        #endregion

        /// <summary>
        /// 默认构造函数，创建一个具有默认参数的轴
        /// </summary>
        public Axis()
        {
            _card = null;
            _axisID = 0;
            _Name = "";
            _ratio = 10000.0;
            _lead = 10.0;
            _gratingScale = 1.0;
            _errorBand = 0.1;
            _isEnableHome = true;
            _homeVel = 5;
            _homeAcc = 50;
            _homeOffset = 0;
            _homeDir = DIR_ENUM.Negative;
            _homeMode = PRA_HOME_ENUM.HOME_MODE_ORG;
            _homeCure = PRA_SF_ENUM.S_CURVE;
            _workVel = 5;
            _workAcc = 50;
            _workDec = 50;
            _jogAcc = 50;
            _jogDec = 50;
            this._userLimitP = 1000.0;
            this._userLimitN = -1000;
            _jogSF = 0.5;
        }
        /// <summary>
        /// 带参数的构造函数
        /// </summary>
        /// <param name="card">轴所属卡</param>
        /// <param name="axisID">轴号</param>
        /// <param name="axisName">轴名称，自定义</param>
        /// <param name="axisList">添加到绑定列表中</param>
        public Axis(IMotionCard card, int axisID, string axisName, BindingList<Axis> axisList)
        {
            _card = card;
            _axisID = axisID;
            _Name = axisName;
            _ratio = 10000.0;
            _lead = 10.0;
            _gratingScale = 1.0;
            _errorBand = 0.1;
            _isEnableHome = true;
            _homeVel = 5;
            _homeAcc = 50;
            _homeOffset = 0;
            _homeDir = DIR_ENUM.Negative;
            _homeMode = PRA_HOME_ENUM.HOME_MODE_ORG;
            _homeCure = PRA_SF_ENUM.S_CURVE;
            _workVel = 5;
            _workAcc = 50;
            _workDec = 50;
            _jogAcc = 50;
            _jogDec = 50;
            this._userLimitP = 1000.0;
            this._userLimitN = -1000;
            _jogSF = 0.5;
        }
        /// <summary>
        /// 深度复制当前对象
        /// </summary>
        /// <returns></returns>
        public Axis DeepCopy()
        {
            object retval;
            using (MemoryStream ms = new MemoryStream())
            {
                BinaryFormatter bf = new BinaryFormatter();
                //将当前对象序列化
                bf.Serialize(ms, this);
                ms.Seek(0, SeekOrigin.Begin);
                //反序列化成对象
                retval = bf.Deserialize(ms);
                ms.Close();
            }
            Axis axis = (Axis)retval;
            return axis;
        }
        /// <summary>
        /// 等待运动停止
        /// </summary>
        /// <param name="timeout">超时时间</param>
        /// <returns>0:运动完成，1运动超时停止，2外部命名停止，3掉使能停止</returns>
        public int WaitMoveDone(double targetPos, int timeout = int.MaxValue)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Restart();
            try
            {
                while (true)
                {
                    if (stopwatch.ElapsedMilliseconds > timeout)
                    {
                        StopMoveEmg();
                        return 1;//超时停止
                    }
                    if (this._isStop)
                    {
                        StopMoveEmg();
                        return 2;//外部命令停止
                    }
                    if (GetServoOn() == false)
                    {
                        StopMoveEmg();
                        return 3;
                    }
                    if (!IsMoving())
                    {
                        double cmdPos = GetPos();
                        double errPos = Math.Abs(cmdPos - targetPos);
                        if (errPos < ErrBand)
                        {
                            return 0;//完成
                        }
                    }
                    Thread.Sleep(1);
                }
            }
            catch (Exception ex)
            {
                throw new AxisException("WaitMoveDone Exception(axisId:" + _axisID + ")! " + ex.Message + ex.StackTrace);
            }
        }

        /// <summary>
        /// 等待运动停止
        /// </summary>
        /// <param name="timeout">超时时间</param>
        /// <returns>0:运动完成，1运动超时停止，2外部命名停止，3掉使能停止</returns>
        public int WaitMoveDone(int timeout = int.MaxValue)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Restart();
            try
            {
                while (true)
                {
                    if (stopwatch.ElapsedMilliseconds > timeout)
                    {
                        StopMoveEmg();
                        return 1;//超时停止
                    }
                    if (this._isStop)
                    {
                        StopMoveEmg();
                        return 2;//外部命令停止
                    }
                    if (GetServoOn() == false)
                    {
                        StopMoveEmg();
                        return 3;
                    }
                    if (!IsMoving())
                    {
                        return 0;//完成
                    }
                    Thread.Sleep(1);
                }
            }
            catch (Exception ex)
            {
                throw new AxisException("WaitMoveDone Exception(axisId:" + _axisID + ")! " + ex.Message + ex.StackTrace);
            }
        }
        /// <summary>
        /// 等待回零停止
        /// </summary>
        /// <param name="timeout">超时时间</param>
        /// <returns>0:回零完成，1回零超时停止，2外部命名停止，3掉使能停止</returns>
        public int WaitHomeMoveDone(int timeout = int.MaxValue)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Restart();
            try
            {
                while (true)
                {
                    if (stopwatch.ElapsedMilliseconds > timeout)
                    {
                        StopMoveEmg();
                        if (Card is LCT_M60)//M60卡在回零完成后需要切换模式
                        {
                            Ec6000_HomeMove.M60_StopHome((short)_axisID, (short)Card.CardID);
                        }
                        return 1;//超时停止
                    }
                    if (this._isStop)
                    {
                        StopMoveEmg();
                        if (Card is LCT_M60)//M60卡在回零完成后需要切换模式
                        {
                            short sts = 0;
                            Ec6000_HomeMove.M60_StopHome((short)_axisID, (short)Card.CardID);
                        }
                        return 2;//外部命令停止
                    }
                    if (GetServoOn() == false)
                    {
                        StopMoveEmg();
                        if (Card is LCT_M60)//M60卡在回零完成后需要切换模式
                        {
                            short sts = 0;
                            Ec6000_HomeMove.M60_StopHome((short)_axisID, (short)Card.CardID);
                        }
                        return 3;
                    }
                    if (!IsMoving() && !IsHoming())
                    {
                        if (Card is LCT_M60)//M60卡在回零完成后需要切换模式
                        {
                            short sts = 0;
                            Ec6000_HomeMove.M60_WaitHoming((short)_axisID, 30 * 1000, ref sts, (short)Card.CardID);
                            //Ec6000_HomeMove.M60_StopHome((short)_axisID, (short)Card.CardID);
                        }

                        double errPos = GetErrPos();
                        if (Math.Abs(errPos) <= ErrBand)
                        {
                            return 0;//完成
                        }
                    }
                    Thread.Sleep(1);
                }
            }
            catch (Exception ex)
            {
                throw new AxisException("WaitHomeMoveDone Exception(axisId:" + _axisID + ")! " + ex.Message + ex.StackTrace);
            }
        }

        private bool IsHoming()
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            try
            {

                return _card.IsHoming(_axisID);
            }
            catch (Exception ex)
            {
                throw new AxisException("IsHoming Exception(axisId:" + _axisID + ")! " + ex.Message + ex.StackTrace);
            }
        }

        public bool StopMoveDec()
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            bool ret = false;
            try
            {
                ret = _card.StopMove((short)_axisID, _workAcc * Ratio);
            }
            catch (Exception ex)
            {
                throw new AxisException("StopMove Exception(axisId:" + _axisID + ")! " + ex.Message + ex.StackTrace);
            }
            return ret;
        }
        public bool StopMoveEmg()
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            bool ret = false;
            try
            {
                ret = _card.StopEmg((short)_axisID);
            }
            catch (Exception ex)
            {
                throw new AxisException("StopMove Exception(axisId:" + _axisID + ")! " + ex.Message + ex.StackTrace);
            }
            return ret;
        }
        public bool IsMoving()
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            try
            {
                return _card.IsMoving(_axisID);
            }
            catch (Exception ex)
            {
                throw new AxisException("IsMoving Exception(axisId:" + _axisID + ")! " + ex.Message + ex.StackTrace);
            }
        }

        public bool HomeMove()
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            if (IsStop == true)
            {
                return false;
            }
            try
            {
                SWITCH_ENUM sWITCH_ENUM = SWITCH_ENUM.Reserved;
                if (_isEnableUserLimit == true)
                {
                    sWITCH_ENUM = SWITCH_ENUM.Enable;
                }
                else
                {
                    sWITCH_ENUM = SWITCH_ENUM.Disable;
                }
                if (IsEnableHome)
                    return _card.HomeMove((short)_axisID,
                                          _homeMode,
                                          _homeDir,
                                          _homeCure,
                                          _homeAcc * Ratio,
                                          _homeVel * Ratio,
                                          _homeStartVel * Ratio,
                                          _homeOffset * Ratio,
                                          _stopDec * Ratio,
                                          sWITCH_ENUM,
                                          _userLimitN,
                                          _userLimitP);
                else
                    return true;
            }
            catch (Exception ex)
            {
                throw new AxisException("HomeMove Exception!" + ex.Message + ex.StackTrace);
            }
        }

        public bool MoveJog(DIR_ENUM dir, double vm = 0.0)
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            if (IsStop == true)
            {
                return false;
            }
            try
            {
                //用velocity move with Vm代替Jog
                return _card.MoveVel((short)_axisID, dir, _jogAcc * Ratio, _jogDec * Ratio, vm * Ratio, _jogSF);
            }
            catch (Exception ex)
            {
                throw new AxisException("MoveJog Exception!" + ex.Message + ex.StackTrace);
            }
        }
        //VelocityProfile
        public bool MoveAbs(VelocityProfile vp)
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            if (IsStop == true)
            {
                return false;
            }
            if (((vp.Pos > this._userLimitP) || (vp.Pos < this._userLimitN)) && _isEnableUserLimit)
            {
                throw new AxisException("Axis[" + _axisID + "]:MoveAbs Error!" + "目标位置:" + vp.Pos.ToString() + "超限");
            }
            if (MaxVel <= vp.MoveVel)
            {
                vp.MoveVel = MaxVel;
            }

            try
            {
                return _card.PTPMove((short)_axisID, PRA_OPTION_ENUM.Absolute, vp.MoveVel * Ratio, vp.Acc * Ratio, vp.Dec * Ratio, vp.Pos * Ratio);
            }
            catch (Exception ex)
            {

                throw new AxisException("Axis[" + _axisID + "]:MoveAbs Exception" + ex.Message + ex.StackTrace);
            }
        }
        public bool MoveAbs(double position, double vm, double acc, double dec)
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            if (IsStop == true)
            {
                return false;
            }
            if (((position > this._userLimitP) || (position < this._userLimitN)) && _isEnableUserLimit)
            {
                throw new AxisException("Axis[" + _axisID + "]:MoveAbs Error!" + "目标位置:" + position.ToString() + "超限");
            }

            try
            {
                return _card.PTPMove((short)_axisID, PRA_OPTION_ENUM.Absolute, vm * Ratio, acc * Ratio, dec * Ratio, position * Ratio);
            }
            catch (Exception ex)
            {

                throw new AxisException("Axis[" + _axisID + "]:MoveAbs Exception" + ex.Message + ex.StackTrace);
            }
        }

        public bool MoveLine()
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            throw new NotImplementedException();
        }

        public bool MoveRel(double distance, double vm, double acc, double dec)
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            if (IsStop == true)
            {
                return false;
            }
            double curPos = this.GetPos();

            if ((((distance + curPos) > this._userLimitP) || ((distance + curPos) < this._userLimitN)) && _isEnableUserLimit)
            {
                throw new AxisException("Axis[" + _axisID + "]:MoveRel Error!" + "目标位置:" + distance.ToString() + "超限");
            }

            try
            {
                return _card.PTPMove((short)_axisID, PRA_OPTION_ENUM.Relative, vm * Ratio, acc * Ratio, dec * Ratio, distance * Ratio);
            }
            catch (Exception ex)
            {

                throw new AxisException("Axis[" + _axisID + "]:MoveRel Exception" + ex.Message + ex.StackTrace);
            }
        }
        public bool MoveRel(VelocityProfile vp)
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            if (IsStop == true)
            {
                return false;
            }
            double distance = vp.Pos;
            double vm = vp.MoveVel;
            double acc = vp.Acc;
            double dec = vp.Dec;

            double curPos = this.GetPos();

            if ((((distance + curPos) > this._userLimitP) || ((distance + curPos) < this._userLimitN)) && _isEnableUserLimit)
            {
                throw new AxisException("Axis[" + _axisID + "]:MoveRel Error!" + "目标位置:" + distance.ToString() + "超限");
            }
            if (MaxVel < vp.MoveVel)
            {
                vp.MoveVel = MaxVel;
            }
            try
            {
                return _card.PTPMove((short)_axisID, PRA_OPTION_ENUM.Relative, vm * Ratio, acc * Ratio, dec * Ratio, distance * Ratio);
            }
            catch (Exception ex)
            {

                throw new AxisException("Axis[" + _axisID + "]:MoveRel Exception" + ex.Message + ex.StackTrace);
            }
        }

        public bool MoveInterpolation(List<VelocityProfile> vpList)
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            try
            {
                if (IsStop == true)
                {
                    return false;
                }

                double vm = 0;
                double acc = 0;
                if (vpList != null && vpList.Count > 0)
                {
                    vm = vpList[0].MoveVel;
                    acc = vpList[0].Acc;
                }
                List<int> axisIdList = new List<int>();
                List<double> posList = new List<double>();
                foreach (var vp in vpList)
                {
                    if (((vp.Pos > this._userLimitP) || (vp.Pos < this._userLimitN)) && _isEnableUserLimit)
                    {
                        throw new AxisException("Axis[" + _axisID + "]:MoveAbs Error!" + "目标位置:" + vp.Pos.ToString() + "超限");
                    }
                    if (MaxVel <= vp.MoveVel)
                    {
                        vp.MoveVel = MaxVel;
                    }

                    axisIdList.Add(vp.AxisId);
                    posList.Add(vp.Pos * Ratio);
                }
                if (axisIdList.Count < 2 || axisIdList.Count > 6)
                {
                    throw new AxisException($"Axis[{_axisID}]:InterPolationLine Move Error! 插入轴超限{axisIdList.Count}");
                }
                return _card.InterPolationLine(axisIdList.ToArray(), posList.ToArray(), PRA_OPTION_ENUM.Absolute, vm * Ratio, acc * Ratio);
                //return true;
            }
            catch (Exception ex)
            {
                throw new AxisException("StartGear Exception! " + ex.Message + ex.StackTrace);
            }
        }

        public bool ServoOff()
        {
            if (_card.Initialized == false)
            {
                return false;
            }
            try
            {
                return _card.ServoOff(_axisID);
            }
            catch (Exception ex)
            {
                throw new AxisException("Axis[" + _axisID + "]:ServoOff Exception ! " + ex.Message + ex.StackTrace);
            }
        }

        public bool ServoOn()
        {
            if (_card.Initialized == false)
            {
                return false;
            }
            try
            {
                return _card.ServoON(_axisID);
            }
            catch (Exception ex)
            {
                throw new AxisException("Axis[" + _axisID + "]:ServoOn Exception ! " + ex.Message + ex.StackTrace);
            }
        }

        public bool ClearAlarm()
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            try
            {
                return _card.ClearAlarm((short)_axisID);
            }
            catch (Exception ex)
            {
                throw new AxisException("Axis[" + _axisID + "]:ServoOn Exception ! " + ex.Message + ex.StackTrace);
            }
        }
        /// <summary>
        /// 获取轴的报警状态
        /// true：报警，false:正常
        /// </summary>
        /// <returns></returns>
        public bool GetAlarm()
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            try
            {
                return _card.GetALMStatus((short)_axisID);
            }
            catch (Exception ex)
            {
                throw new AxisException("GetAlarm Exception! " + ex.Message + ex.StackTrace);
            }

        }

        public double GetCmdPos()
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            double position = 0.0;
            try
            {
                if (_card.GetCmdPosition((short)_axisID, ref position) == true)
                {
                    return position / Ratio;
                }
                else
                {
                    throw new AxisException("GetCmdPos Error! ");
                }
            }
            catch (Exception ex)
            {
                throw new AxisException("GetCmdPos Exception! " + ex.Message + ex.StackTrace);
            }
        }

        public double GetPos()
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            double position = 0.0;
            try
            {
                if (_card.GetFeedbackPosition((short)_axisID, ref position) == true)
                {
                    return position / Ratio;
                }
                else
                {
                    throw new AxisException("GetPos Error! ");
                }
            }
            catch (Exception ex)
            {
                throw new AxisException("GetPos Exception! " + ex.Message + ex.StackTrace);
            }
        }

        public double GetTargetPos()
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            double position = 0.0;
            try
            {
                if (_card.GetTargetPosition((short)_axisID, ref position) == true)
                {
                    return position / Ratio;
                }
                else
                {
                    throw new AxisException("GetTargetPos Error! ");
                }
            }
            catch (Exception ex)
            {
                throw new AxisException("GetTargetPos Exception! " + ex.Message + ex.StackTrace);
            }
        }

        public double GetErrPos()
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            double position = 0.0;
            try
            {
                if (_card.GetErrorPosition((short)_axisID, ref position) == true)
                {
                    return position / Ratio;
                }
                else
                {
                    throw new AxisException("GetErrPos Error! ");
                }
            }
            catch (Exception ex)
            {
                throw new AxisException("GetErrPos Exception! " + ex.Message + ex.StackTrace);
            }
        }

        public bool GetORG()
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            try
            {
                return _card.GetORGStatus((short)_axisID);
            }
            catch (Exception ex)
            {
                throw new AxisException("GetORG Exception! " + ex.Message + ex.StackTrace);
            }
        }

        public bool GetMEL()
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            try
            {
                return _card.GetMELStatus((short)_axisID);
            }
            catch (Exception ex)
            {
                throw new AxisException("GetMEL Exception! " + ex.Message + ex.StackTrace);
            }
        }

        public bool GetPEL()
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            try
            {
                return _card.GetPELStatus((short)_axisID);
            }
            catch (Exception ex)
            {
                throw new AxisException("GetPELStatus Exception! " + ex.Message + ex.StackTrace);
            }
        }
        public bool GeINP()
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            try
            {
                return _card.GetINPStatus((short)_axisID);
            }
            catch (Exception ex)
            {
                throw new AxisException("GeINP Exception! " + ex.Message + ex.StackTrace);
            }
        }
        public bool GetEMG()
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            try
            {
                return _card.GetEMGStatus((short)_axisID);
            }
            catch (Exception ex)
            {
                throw new AxisException("GeEMG Exception! " + ex.Message + ex.StackTrace);
            }
        }

        //ASTP CSTP NSTP HMV
        public bool GetASTP()
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            try
            {
                return _card.GetASTPStatus((short)_axisID);
            }
            catch (Exception ex)
            {
                throw new AxisException("GetASTP Exception! " + ex.Message + ex.StackTrace);
            }
        }
        public bool GetCSTP()
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            try
            {
                return _card.GetCSTPStatus((short)_axisID);
            }
            catch (Exception ex)
            {
                throw new AxisException("GetCSTP Exception! " + ex.Message + ex.StackTrace);
            }
        }
        public bool GetNSTP()
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            try
            {
                return _card.GetNSTPStatus((short)_axisID);
            }
            catch (Exception ex)
            {
                throw new AxisException("GetNSTP Exception! " + ex.Message + ex.StackTrace);
            }
        }
        public bool GetHMV()
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            try
            {
                return _card.GetHMVStatus((short)_axisID);
            }
            catch (Exception ex)
            {
                throw new AxisException("GetHMV Exception! " + ex.Message + ex.StackTrace);
            }
        }
        public bool GetServoOn()
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            try
            {
                return _card.GetServoOnStatus((short)_axisID);
            }
            catch (Exception ex)
            {
                throw new AxisException("GetServoOn Exception! " + ex.Message + ex.StackTrace);
            }
        }

        public bool SetPos(double pos)
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            try
            {
                return _card.SetPos((short)_axisID, pos * Ratio);
            }
            catch (Exception ex)
            {
                throw new AxisException("GetServoOn Exception! " + ex.Message + ex.StackTrace);
            }
        }

        public bool StartGear(Axis axis, GEAR_MODE mode)
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            try
            {
                return _card.StartGear((short)axis.AxisID, mode);
            }
            catch (Exception ex)
            {
                throw new AxisException("StartGear Exception! " + ex.Message + ex.StackTrace);
            }
        }
        public bool InitAxis()
        {
            if (_card.Initialized == false)
            {
                throw new AxisException($"{_card.CardType} Card Is NotInitialized");
            }
            throw new NotImplementedException();
        }


    }
}
